/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package com.wjk.kylin.core.job;

import com.wjk.kylin.core.constant.Constants;
import com.wjk.kylin.core.constant.ScheduleConstants;
import com.wjk.kylin.core.utils.ExceptionUtil;
import com.wjk.kylin.core.utils.SpringContextHolder;
import com.wjk.kylin.modules.system.schedule.entity.Schedule;
import com.wjk.kylin.modules.system.schedule.entity.ScheduleLog;
import com.wjk.kylin.modules.system.schedule.service.IScheduleLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.lang.reflect.Method;
import java.util.Date;


/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
@Slf4j
public class ScheduleJob extends QuartzJobBean {

	/**
	 * 线程本地变量
	 */
	private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		/**devtools 不能转换*/
		Schedule schedule = (Schedule) context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES);

		try {
			before(schedule);

			doExecute(schedule);

			after(schedule, null);
		} catch (Exception e) {
			log.error("任务执行异常  - ：", e);
			after(schedule, e);
		}
    }

	/**
	 * 执行前
	 *
	 * @param schedule 系统计划任务
	 */
	protected void before( Schedule schedule) {
		log.debug("任务开始执行，任务ID：{},任务名称：{}",schedule.getId(),schedule.getJobName());

		threadLocal.set(new Date());
	}

	/**
	 * 执行后
	 *
	 * @param schedule 系统计划任务
	 */
	protected void after(Schedule schedule, Exception e) {
		log.debug("任务结束执行，任务ID：{},任务名称：{}",schedule.getId(),schedule.getJobName());

		Date startTime = threadLocal.get();
		threadLocal.remove();

		final ScheduleLog scheduleLog = new ScheduleLog();
		scheduleLog.setJobId(schedule.getId());
		scheduleLog.setJobName(schedule.getJobName());
		scheduleLog.setJobGroup(schedule.getJobGroup());
		scheduleLog.setBeanName(schedule.getBeanName());
		scheduleLog.setParams(schedule.getParams());
		scheduleLog.setCreateDate(startTime);
		scheduleLog.setUpdateDate(new Date());
		if (e != null) {
			scheduleLog.setStatus(Constants.FAIL);
			String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
			scheduleLog.setJobMessage(errorMsg);
			log.error("任务结束执行异常",e);
		} else {
			scheduleLog.setJobMessage("执行成功");
			scheduleLog.setStatus(Constants.SUCCESS);
		}

		// 写入数据库当中
		SpringContextHolder.getBean(IScheduleLogService.class).save(scheduleLog);
	}

	/**
	 * 执行方法
	 *
	 * @param schedule 系统计划任务
	 * @throws Exception 执行过程中的异常
	 */
	protected void doExecute(Schedule schedule) throws Exception{

		Object target = SpringContextHolder.getBean(schedule.getBeanName());
		Method method = target.getClass().getDeclaredMethod("run", String.class);
		method.invoke(target, schedule.getParams());

	}
}
